package com.ziytek.web.citizen.service;

import com.google.gson.Gson;
import com.ziytek.web.citizen.caffeine.CachePutOrGet;
import com.ziytek.web.citizen.config.caffeine.CaffeineUtil;
import com.ziytek.web.citizen.constant.NumConstant;
import com.ziytek.web.citizen.constant.ServerConstant;
import com.ziytek.web.citizen.enums.ErrorTypeEnum;
import com.ziytek.web.citizen.enums.StepTypeNoEnum;
import com.ziytek.web.citizen.event.OperationEvent;
import com.ziytek.web.citizen.mapper.BoardConfigMapper;
import com.ziytek.web.citizen.mapper.OperationDetailMapper;
import com.ziytek.web.citizen.mapper.SettingDetailMapper;
import com.ziytek.web.citizen.model.bean.CapStatsVo;
import com.ziytek.web.citizen.model.bean.CommandIssuedSuccess;
import com.ziytek.web.citizen.model.bean.InterruptStatsCacheVo;
import com.ziytek.web.citizen.model.vo.OperationVo;
import com.ziytek.web.citizen.pojo.basic.BoardConfig;
import com.ziytek.web.citizen.pojo.basic.OperationDetail;
import com.ziytek.web.citizen.util.KeyUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/***
 * 工步指令操作服务类
 * @author fenghx
 * */
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class CommandOperationService {
    private final Gson gson;
    private final ApplicationContext context;
    private final CachePutOrGet cachePutOrGet;
    private final BatchNoService batchNoService;
    private final BoardConfigMapper boardConfigMapper;
    private final SettingDetailMapper settingDetailMapper;
    private final ChannelStatsService channelStatsService;
    private final OperationDetailMapper operationDetailMapper;
    private final OperationVoCacheService operationVoCacheService;
    private final OperationDetailEasyService operationDetailEasyService;


    public void updateCache(CommandIssuedSuccess command, boolean firstCommand) {
        // 单个通道指令下发操作保存
        if (null != command && command.isSingleChannel()) {
            single(command);
            return;
        }

        wholeChannel(command, firstCommand);
    }

    /***
     * 终止指令更新操作记录及缓存
     * */
    public void endUpdateCache(CommandIssuedSuccess command) {
        //单个通道放电工艺
        channelStatsService.singleStats(command);
        // 整体放电工艺
        channelStatsService.allChannelStats(command);

        // 单个通道指令下发操作保存
        if (null != command && command.isSingleChannel()) {
            endSingle(command);
            return;
        }

        endWholeChannel(command);
    }

    public void interruptReIssuedUpdateCache(CommandIssuedSuccess command) {
        // 单个通道指令下发操作保存
        if (null != command && command.isSingleChannel()) {
            interruptReIssuedSingle(command);
            return;
        }

        interruptReIssuedWholeChannel(command);
    }


    private void wholeChannel(CommandIssuedSuccess command, boolean firstCommand) {
        List<BoardConfig> queryBoardConfigs = boardConfigMapper.queryAllList();
        Assert.notEmpty(queryBoardConfigs, "boardConfigs is empty");
        Assert.notNull(command, "commandOperationEventListener commandIssued  is null");

        log.info("[整体]下发指令操作,开始更新表操作信息:{}", gson.toJson(command));

        // 获取批次号
        var batchNo = batchNoService.queryOne(Integer.parseInt(command.getReqCabinetNo()));
        var batchNoString = null != batchNo ? batchNo.getBatchNo() : "0000";
        var timeCount = settingDetailMapper.queryTimeCountByStepId(command.getStepId(), command.getOrder());

        List<OperationDetail> opsList = operationDetailMapper.findDetailByCabinetNo(command.getReqCabinetNo());
        //log.info("[整体]循环剔除不是整体opsList:{}", opsList.size());
        List<BoardConfig> boardConfigs = new ArrayList<>();
        if (!CollectionUtils.isEmpty(opsList) && opsList.size() != NumConstant.INT_ONE_TWO_EIGHT) {
            if (firstCommand) {
                boardConfigs.addAll(queryBoardConfigs);
            } else {
                for (var bc : queryBoardConfigs) {
                    if (opsList.stream().anyMatch(os -> null != os
                            && os.getSingleType() == ServerConstant.SINGLE_TYPE_ALL
                            && os.getBoardAddress().equals(bc.getAddress())
                            && os.getCellNum().equals(bc.getChannelNo()))) {
                        boardConfigs.add(bc);
                    }
                }
            }
        }

        if (CollectionUtils.isEmpty(opsList)) {
            boardConfigs.addAll(queryBoardConfigs);
        }

        if (CollectionUtils.isEmpty(boardConfigs)) {
            boardConfigs.addAll(queryBoardConfigs);
        }

        for (var os : opsList) {
            // 剔除正在执行的单个通道的
            var isSingleAndIng = null != os
                    && ServerConstant.SINGLE_TYPE_SINGLE == os.getSingleType()
                    && ServerConstant.START_FLAG_NORMAL == os.getStartFlag()
                    && null != os.getEndTime()
                    && os.getEndTime() > System.currentTimeMillis();

            var error = null != os && ServerConstant.START_FLAG_ERROR == os.getStartFlag() && NumConstant.INT_ONE != command.getOrder();

            // 单个通道的
            var notFirst = !firstCommand && null != os && ServerConstant.SINGLE_TYPE_SINGLE == os.getSingleType();
            if (isSingleAndIng || error || notFirst) {
                //log.info("[整体]循环剔除单个通道执行中或者异常的而且结束时间未到:{}", gson.toJson(os));
                boardConfigs.removeIf(b -> null != b && b.getAddress().equals(os.getBoardAddress()) && b.getChannelNo().equals(os.getCellNum()));
            }
        }

        // 是否是最后一个操作
        boolean isLastOperation = isLast(command.getStepId(), command.getOrder());
        if (isLastOperation) {
            log.info("[整体]指令操作下发,最后一个操作:size:{}-{}", boardConfigs.size(), gson.toJson(command));
            operationVoCacheUpdateAllChannel(boardConfigs, command, batchNoString, timeCount);
            return;
        }

        if (NumConstant.INT_ONE == command.getOrder()) {
            if (CollectionUtils.isEmpty(boardConfigs)) {
                boardConfigs.addAll(queryBoardConfigs);
            }

            allFirstCommand(command, boardConfigs, batchNoString, timeCount);
            log.info("[整体order=1]下发指令操作,更新表操作信息结束:size:{}-{}", boardConfigs.size(), gson.toJson(command));
            return;
        }

        nextCommand(command, boardConfigs, batchNoString, timeCount);

        log.info("[整体]下发指令操作,更新表操作信息结束:{}", gson.toJson(command));
    }

    private void nextCommand(CommandIssuedSuccess command, List<BoardConfig> boardConfigs, String batchNoString, int timeCount) {
        log.info("[整体]循环剔除不是整体的boardConfigs:{}", boardConfigs.size());
        final int[] serial = {NumConstant.INT_ZERO};
        var thread = Thread.startVirtualThread(() -> {
            for (var b : boardConfigs) {
                // 最后一个工步操作是搁置类型
                serial[0]++;
                oneOperationUpdate(command, b, serial[0], batchNoString, timeCount);
            }
        });

        try {
            thread.join();
        } catch (Exception e) {
            log.error("operation error", e);
        }
    }

    private void allFirstCommand(CommandIssuedSuccess command, List<BoardConfig> boardConfigs, String batchNo, long endTime) {
        long start = System.currentTimeMillis();
        log.info("[整体]指令操作下发,第一个操作:{}", gson.toJson(command));

        var cabinetNo = Integer.parseInt(command.getReqCabinetNo()) + "";
        // 先删除再查询
        //operationDetailMapper.deleteDetailByCabinetNo(cabinetNo);
        var ops = operationDetailMapper.findDetailByNo(cabinetNo);

        var pair = getOperationPair(boardConfigs, ops, command, batchNo, endTime);

        log.info("[整体]指令操作下发,获取操作信息处理耗时:{}ms", System.currentTimeMillis() - start);

        if (!CollectionUtils.isEmpty(pair.getLeft())) {
            // 新增表数据
            long addTime = System.currentTimeMillis();
            operationDetailEasyService.insertBatchSomeColumn(pair.getLeft());
            log.info("[整体]指令操作下发,批量新增表操作信息总数:{}ms-cab:{}-{}", System.currentTimeMillis() - addTime, cabinetNo, pair.getLeft().size());
        }
        if (!CollectionUtils.isEmpty(pair.getRight())) {
            // 更新表数据
            long updateTime = System.currentTimeMillis();
            operationDetailEasyService.updateBatchById(pair.getRight());
            log.info("[整体]指令操作下发,批量更新表操作信息总数:{}ms-cab:{}-{}", System.currentTimeMillis() - updateTime, cabinetNo, pair.getRight().size());
        }

        start = System.currentTimeMillis();
        List<OperationVo> opsList = operationDetailMapper.findListLeftOn(cabinetNo, command.getOrder());
        var thread0 = Thread.startVirtualThread(() -> {
            for (var b : boardConfigs) {
                // 最后一个工步操作是搁置类型
                oneOperationUpdateFirst(opsList, command, b);
            }
        });

        try {
            thread0.join();
        } catch (Exception e) {
            log.error("operation error", e);
        }

        log.info("[整体]指令操作下发,更新表操作信息结束,耗时:{}ms-{}", System.currentTimeMillis() - start, gson.toJson(command));
    }

    private void endWholeChannel(CommandIssuedSuccess commandIssued) {
        List<BoardConfig> boardConfigs = boardConfigMapper.queryAllList();
        Assert.notEmpty(boardConfigs, "endWholeChannel boardConfigs is empty");
        Assert.notNull(commandIssued, "endWholeChannel commandOperationEventListener commandIssued  is null");

        log.info("[整体]终止下发指令操作,command：{}", gson.toJson(commandIssued));
        long start = System.currentTimeMillis();

        List<OperationDetail> opsList = operationDetailMapper.findDetailByCabinetNo(commandIssued.getReqCabinetNo());
        for (var o : opsList) {
            if (null != o && ServerConstant.SINGLE_TYPE_SINGLE == o.getSingleType() && ServerConstant.START_FLAG_NORMAL == o.getStartFlag()
                    && null != o.getEndTime() && o.getEndTime() > System.currentTimeMillis()) {

                boardConfigs.removeIf(b -> null != b && b.getAddress().equals(o.getBoardAddress()) && b.getChannelNo().equals(o.getCellNum()));
            }
        }


        List<OperationVo> opvList = operationDetailMapper.findListLeftOnByList(commandIssued.getReqCabinetNo());

        log.info("[整体]终止下发指令操作,更新表操作信息总数:{}-boardConfigs size:{}", opsList.size(), boardConfigs.size());
        var thread = Thread.startVirtualThread(() -> {
            for (var b : boardConfigs) {
                // 最后一个工步操作是搁置类型
                var one = new CommandIssuedSuccess();
                BeanUtils.copyProperties(commandIssued, one);
                one.setDoor(b.getDoor());
                one.setBoardNo(b.getLineNo());
                one.setChannelNo(b.getChannelNo());
                //endSingleAll(opsList, one, b);
                endSingleAll(opvList, one, b);
            }
        });

        try {
            thread.join();
        } catch (Exception e) {
            log.error("operation error", e);
        }

        // 删除缓存
        var cacheKey = CaffeineUtil.getCacheKey(Integer.parseInt(commandIssued.getReqCabinetNo()), 255, 255);
        CaffeineUtil.deleteStartWith(CaffeineUtil.CACHE_KEY_COMMAND + cacheKey);
        log.info("[整体]终止下发指令操作完成耗时:{}ms", System.currentTimeMillis() - start);
    }


    private void interruptReIssuedWholeChannel(CommandIssuedSuccess commandIssued) {
        List<BoardConfig> boardConfigs = boardConfigMapper.queryAllList();
        Assert.notEmpty(boardConfigs, "boardConfigs is empty");
        Assert.notNull(commandIssued, "commandOperationEventListener commandIssued  is null");

        var thread = Thread.startVirtualThread(() -> {
            for (var b : boardConfigs) {
                var opKey = KeyUtil.commandOperateKey(commandIssued.getReqCabinetNo(), b.getAddress(), b.getChannelNo());
                var od = operationDetailMapper.findOneDetail(commandIssued.getReqCabinetNo(), b.getAddress(), b.getChannelNo(), b.getLineNo());
                // 剔除正在执行的单个通道的
                var isSingleAndIng = od != null && ServerConstant.SINGLE_TYPE_SINGLE == od.getSingleType();
                // && ServerConstant.START_FLAG_NORMAL == od.getStartFlag()
                // && od.getEndTime() != null
                // && od.getEndTime() > System.currentTimeMillis();
                if (isSingleAndIng) {
                    log.info("单个通道执行中而且结束时间未到:{}", gson.toJson(od));
                    continue;
                }

                if (od == null) {
                    continue;
                }

                od.setCellNum(b.getChannelNo());
                od.setBoardLineNum(b.getLineNo());
                od.setBoardAddress(b.getAddress());
                //od.setSingleType(ServerConstant.SINGLE_TYPE_ALL);

                var cap = od.getInterruptCap();
                var interruptTimeSecond = od.getInterruptTimeSecond();
                interruptReIssuedOperationSaveOrUpdate(commandIssued, od);

                // 增加缓存
                var vo = operationDetailMapper.findLeftOn(commandIssued.getReqCabinetNo(), b.getChannelNo(), b.getAddress());
                if (vo == null || vo.getDetailsStepId() == NumConstant.LONG_LT_TEN || vo.getStartFlag() == ServerConstant.START_FLAG_DISABLE) {
                    continue;
                }

                //log.info("工步指令操作缓存更新，k:{}，vo：{}", opKey, vo);
                vo.setStartFlag(ServerConstant.START_FLAG_NORMAL);
                operationVoCacheService.putOperationVo(opKey, vo);

                var cacheKey = commandIssued.getReqCabinetNo() + CaffeineUtil.CACHE_KEY_SYMBOL + b.getAddress() + CaffeineUtil.CACHE_KEY_SYMBOL + b.getChannelNo();
                // 每个电池通道的工步操作缓存,更新电池容量统计缓存
                //cachePutOrGet.deleteCurrent(cacheKey);
                var stats = cachePutOrGet.getStatsCache(cacheKey);
                interruptReIssuedCacheInit(vo, cacheKey, stats, cap, interruptTimeSecond);
            }
        });

        try {
            thread.join();
        } catch (Exception e) {
            log.error("operation error", e);
        }
    }

    private void single(CommandIssuedSuccess command) {
        Assert.notNull(command, "commandIssued is null");
        log.info("[单通道]下发指令操作,更新表操作信息：{}", gson.toJson(command));

        var door = command.getDoor();
        var channelNo = command.getChannelNo();
        var lineNo = command.getBoardNo() + NumConstant.INT_ONE;
        var bc = boardConfigMapper.queryByDoorAndLineNo(door, lineNo, channelNo);
        if (null == bc) {
            log.info("[单通道]下发指令失败,查询BoardConfig为null command[{}]", gson.toJson(command));
            return;
        }

        var opKey = KeyUtil.commandOperateKey(command.getReqCabinetNo(), bc.getAddress(), bc.getChannelNo());
        var cacheDlKey1 = Integer.parseInt(command.getReqCabinetNo()) + CaffeineUtil.CACHE_KEY_SYMBOL + bc.getAddress() + CaffeineUtil.CACHE_KEY_SYMBOL + bc.getChannelNo();
        cachePutOrGet.delInterruptStatsCache(cacheDlKey1);

        // 最后的结束指令
        if (isLast(command.getStepId(), command.getOrder())) {
            var vo = operationVoCacheService.getOperationVo(opKey);
            if (null != vo) {
                vo.setStartFlag(ServerConstant.START_FLAG_FINISH);
                operationVoCacheService.putOperationVo(opKey, vo);
            }

            if (null != command.getSetType() && !StepTypeNoEnum.STEP_TYPE_SL_NUM.getCode().equals(command.getSetType())) {
                return;
            }
        }

        // 更新工步方案操作记录信息
        var detail = operationDetailMapper.findOneDetailByCellNum(command.getReqCabinetNo(), bc.getAddress(), bc.getChannelNo());
        var error = null != detail && ServerConstant.START_FLAG_ERROR == detail.getStartFlag()
                && NumConstant.INT_ONE != command.getOrder();
        if (error) {
            log.info("单个通道异常的:{}", gson.toJson(detail));
            return;
        }

        var update = true;
        if (null == detail) {
            update = false;
            detail = new OperationDetail();
            detail.setCreateTime(System.currentTimeMillis());
            detail.setStartFlag(ServerConstant.START_FLAG_NORMAL);
        }

        detail.setCellNum(bc.getChannelNo());
        detail.setBoardLineNum(bc.getLineNo());
        detail.setBoardAddress(bc.getAddress());
        detail.setBatterySerial(NumConstant.INT_ONE);
        detail.setSingleType(ServerConstant.SINGLE_TYPE_SINGLE);

        // 获取批次号
        var batchNo = batchNoService.queryOne(Integer.parseInt(command.getReqCabinetNo()));
        var batchNoString = null != batchNo ? batchNo.getBatchNo() : "0000";
        var timeCount = settingDetailMapper.queryTimeCountByStepId(command.getStepId(), command.getOrder());

        operationSaveOrUpdate(command, detail, update, bc.getAddress(), bc.getChannelNo(), batchNoString, timeCount);

        // 工步方案执行,增加操作缓存
        var vo = operationDetailMapper.findLeftOn(command.getReqCabinetNo(), bc.getChannelNo(), bc.getAddress());
        if (vo == null) {
            log.info("[单通道]执行未找到操作信息:{}-{}-{}", command.getReqCabinetNo(), bc.getAddress(), bc.getChannelNo());
            return;
        }

        // 最后的结束指令
        vo.setStartFlag(ServerConstant.START_FLAG_NORMAL);
        log.info("单个通道指令操作,操作缓存更新,address:{},channelNo:{}", bc.getAddress(), bc.getChannelNo());
        vo.setOperationStartTime(System.currentTimeMillis());
        operationVoCacheService.putOperationVo(opKey, vo);

        // 更新容量统计缓存
        var cacheDlKey = command.getReqCabinetNo() + CaffeineUtil.CACHE_KEY_SYMBOL + bc.getAddress() + CaffeineUtil.CACHE_KEY_SYMBOL + bc.getChannelNo();
        // 结束指令下发成功，更新单个电池容量统计缓存
        var endFlag = vo.getDetailsStepId() == NumConstant.LONG_LT_TEN;
        //var isInterrupt = vo != null && vo.getDetailsStepId() == NumConstant.LONG_LT_ZERO;
        var isDisable = vo.getStartFlag() == ServerConstant.START_FLAG_DISABLE;
        log.info("是否是打断指令:{}-{}", isDisable, vo);
        if (!endFlag) {
            var stats = cachePutOrGet.getStatsCache(cacheDlKey);
            cachePutOrGet.deleteCurrent(cacheDlKey);
            cacheInit(cacheDlKey, isDisable, stats, vo);
        }
    }

    private void endSingle(CommandIssuedSuccess commandIssued) {
        Assert.notNull(commandIssued, "endSingle commandIssued is null");
        log.info("[单通道]终止下发指令操作,更新表操作信息：{}", gson.toJson(commandIssued));

        var door = commandIssued.getDoor();
        var channelNo = commandIssued.getChannelNo();
        var lineNo = commandIssued.getBoardNo() + NumConstant.INT_ONE;

        var bc = boardConfigMapper.queryByDoorAndLineNo(door, lineNo, channelNo);
        if (null == bc) {
            return;
        }

        // 更新工步方案操作记录信息
        var detail = operationDetailMapper.findOneDetailByCellNumAndType(commandIssued.getReqCabinetNo(), bc.getAddress(), bc.getChannelNo(), ServerConstant.SINGLE_TYPE_SINGLE);
        if (null == detail) {
            log.error("单个通道终止操作信息更新失败,未查询到操作信息{}-{}-{}", commandIssued.getReqCabinetNo(), bc.getAddress(), bc.getChannelNo());
            return;
        }

        detail.setStartFlag(ServerConstant.START_FLAG_DISABLE);
        detail.setSingleType(ServerConstant.SINGLE_TYPE_SINGLE);
        detail.setUpdateTime(System.currentTimeMillis());
        operationDetailMapper.updateDetail(detail);

        // 工步方案执行,增加操作缓存
        var vo = operationDetailMapper.findLeftOn(commandIssued.getReqCabinetNo(), bc.getChannelNo(), bc.getAddress());
        if (vo == null) {
            log.info("[单通道]执行终止指令未找到操作信息:{}-{}-{}", commandIssued.getReqCabinetNo(), bc.getAddress(), bc.getChannelNo());
            return;
        }

        // 最后的结束指令
        vo.setStartFlag(ServerConstant.START_FLAG_DISABLE);
        var opKey = KeyUtil.commandOperateKey(commandIssued.getReqCabinetNo(), bc.getAddress(), bc.getChannelNo());
        log.info("单个通道终止指令操作,操作缓存更新,address:{},channelNo:{}", bc.getAddress(), bc.getChannelNo());
        operationVoCacheService.putOperationVo(opKey, vo);

        // 更新容量统计缓存
        var cacheDlKey = commandIssued.getReqCabinetNo() + CaffeineUtil.CACHE_KEY_SYMBOL + bc.getAddress() + CaffeineUtil.CACHE_KEY_SYMBOL + bc.getChannelNo();

        var stats = cachePutOrGet.getStatsCache(cacheDlKey);
        boolean isNotNormal = ErrorTypeEnum.LEISURE.getCode() == stats.getT() || ErrorTypeEnum.WAITING.getCode() == stats.getT();
        if (!isNotNormal) {
            stats.setT(ErrorTypeEnum.STOP.getCode());
        }
        cachePutOrGet.putStatsCache(cacheDlKey, stats);
        cachePutOrGet.deleteCurrent(cacheDlKey);

        // 删除缓存
        var cacheKey = CaffeineUtil.getCacheKey(Integer.parseInt(commandIssued.getReqCabinetNo()), bc.getAddress(), bc.getChannelNo());
        CaffeineUtil.deleteStartWith(CaffeineUtil.CACHE_KEY_COMMAND + cacheKey);
    }

    private void endSingleAll(List<OperationVo> ops, CommandIssuedSuccess command, BoardConfig bc) {
        Assert.notNull(bc, "endSingle BoardConfig is null");
        Assert.notNull(command, "endSingle commandIssued is null");
        log.info("[整体单个]终止下发指令操作,更新表操作信息：{}", gson.toJson(command));

        // 工步方案执行,增加操作缓存
        OperationVo vo = null;
        if (!CollectionUtils.isEmpty(ops)) {
            vo = ops.stream().filter(os -> os != null
                    && os.getCellNum().equals(bc.getChannelNo())
                    && os.getBoardAddress().equals(bc.getAddress())
                    && os.getCabinetNo().equals(command.getReqCabinetNo())).findFirst().orElse(null);
        }

        // OperationVo vo = null;
        if (null == vo) {
            vo = operationDetailMapper.findLeftOn(command.getReqCabinetNo(), bc.getChannelNo(), bc.getAddress());
            if (null == vo) {
                log.info("[整体单个]执行终止指令未找到操作信息:{}-{}-{}", command.getReqCabinetNo(), bc.getAddress(), bc.getChannelNo());
                return;
            }
        }

        vo.setSingleType(ServerConstant.SINGLE_TYPE_ALL);
        // 最后的结束指令
        vo.setStartFlag(ServerConstant.START_FLAG_DISABLE);
        var opKey = KeyUtil.commandOperateKey(command.getReqCabinetNo(), bc.getAddress(), bc.getChannelNo());
        log.info("整体单个通道终止指令操作,操作缓存更新,address:{},channelNo:{}", bc.getAddress(), bc.getChannelNo());
        operationVoCacheService.putOperationVo(opKey, vo);

        // 更新容量统计缓存
        var cacheDlKey = command.getReqCabinetNo() + CaffeineUtil.CACHE_KEY_SYMBOL + bc.getAddress() + CaffeineUtil.CACHE_KEY_SYMBOL + bc.getChannelNo();

        var stats = cachePutOrGet.getStatsCache(cacheDlKey);
        boolean isNotNormal = ErrorTypeEnum.LEISURE.getCode() == stats.getT() || ErrorTypeEnum.WAITING.getCode() == stats.getT();
        if (!isNotNormal) {
            stats.setT(ErrorTypeEnum.STOP.getCode());
        }
        cachePutOrGet.putStatsCache(cacheDlKey, stats);
        cachePutOrGet.deleteCurrent(cacheDlKey);

        // 删除缓存
        var cacheKey = CaffeineUtil.getCacheKey(Integer.parseInt(command.getReqCabinetNo()), bc.getAddress(), bc.getChannelNo());
        CaffeineUtil.deleteStartWith(CaffeineUtil.CACHE_KEY_COMMAND + cacheKey);

        // 删除中断缓存
        var cacheInterruptKey = Integer.parseInt(command.getReqCabinetNo()) + CaffeineUtil.CACHE_KEY_SYMBOL + bc.getAddress() + CaffeineUtil.CACHE_KEY_SYMBOL + bc.getChannelNo();
        cachePutOrGet.delInterruptStatsCache(cacheInterruptKey);

        // todo 更新工步方案操作记录信息，发送更新事件
        context.publishEvent(new OperationEvent(command, bc));
    }

    private void interruptReIssuedSingle(CommandIssuedSuccess command) {
        Assert.notNull(command, "interruptReIssuedSingle commandIssued is null");

        var door = command.getDoor();
        var channelNo = command.getChannelNo();
        var lineNo = command.getBoardNo() + NumConstant.INT_ONE;

        // 单个通道
        if (NumConstant.INT_TWO_FIFTY_FIVE != channelNo) {
            oneSingle(command, door, lineNo, channelNo);
            return;
        }

        for (int i = NumConstant.INT_ONE; i <= NumConstant.INT_EIGHT; i++) {
            oneSingle(command, door, lineNo, i);
        }
    }

    private void oneSingle(CommandIssuedSuccess commandIssued, String door, int lineNo, Integer channelNo) {
        var bc = boardConfigMapper.queryByDoorAndLineNo(door, lineNo, channelNo);
        if (null == bc) {
            return;
        }

        var opKey = KeyUtil.commandOperateKey(commandIssued.getReqCabinetNo(), bc.getAddress(), bc.getChannelNo());

        // 更新工步方案操作记录信息
        var detail = operationDetailMapper.findOneDetailByCellNum(commandIssued.getReqCabinetNo(), bc.getAddress(), bc.getChannelNo());
        if (null == detail) {
            return;
        }

        detail.setCellNum(bc.getChannelNo());
        detail.setBoardLineNum(bc.getLineNo());
        detail.setBoardAddress(bc.getAddress());
        detail.setBatterySerial(NumConstant.INT_ONE);
        //detail.setSingleType(ServerConstant.SINGLE_TYPE_SINGLE);

        var cap = detail.getInterruptCap();
        var interruptTimeSecond = detail.getInterruptTimeSecond();
        interruptReIssuedOperationSaveOrUpdate(commandIssued, detail);

        // 工步方案执行,增加操作缓存
        var vo = operationDetailMapper.findLeftOn(commandIssued.getReqCabinetNo(), bc.getChannelNo(), bc.getAddress());
        if (null == vo || NumConstant.LONG_LT_TEN == vo.getDetailsStepId() || ServerConstant.START_FLAG_DISABLE == vo.getStartFlag()) {
            return;
        }

        // 最后的结束指令
        log.info("中断-单个通道指令操作,操作缓存更新,address:{},channelNo:{}", bc.getAddress(), bc.getChannelNo());
        operationVoCacheService.putOperationVo(opKey, vo);

        // 更新容量统计缓存
        var cacheDlKey = commandIssued.getReqCabinetNo() + CaffeineUtil.CACHE_KEY_SYMBOL + bc.getAddress() + CaffeineUtil.CACHE_KEY_SYMBOL + bc.getChannelNo();

        var stats = cachePutOrGet.getStatsCache(cacheDlKey);
        //cachePutOrGet.deleteCurrent(cacheDlKey);
        interruptReIssuedCacheInit(vo, cacheDlKey, stats, cap, interruptTimeSecond);
    }

    private void cacheInit(String cacheDlKey, boolean isDisable, CapStatsVo stats, OperationVo ovo) {
        boolean notUpdate = stats == null || isDisable;
        if (notUpdate) {
            return;
        }

        var vo = new CapStatsVo();
        BeanUtils.copyProperties(stats, vo);
        vo.setTs(NumConstant.DOUBLE_ZERO);
        vo.setAc(NumConstant.DOUBLE_ZERO);
        if (null != ovo) {
            vo.setVo(ovo);
            vo.setCty(ovo.getSetType());
        }

        vo.setC(NumConstant.DOUBLE_ZERO);
        boolean notNormal = ErrorTypeEnum.LEISURE.getCode() == stats.getT() || ErrorTypeEnum.WAITING.getCode() == stats.getT();
        if (!notNormal) {
            vo.setT(ErrorTypeEnum.EXECUTING.getCode());
        }

        vo.setEt(ServerConstant.ERROR_EXCEPTION_TYPE_NORMAL);
        cachePutOrGet.putStatsCache(cacheDlKey, vo);
    }

    private void interruptReIssuedCacheInit(OperationVo ovo, String cacheDlKey, CapStatsVo vo, Float interruptCap, Long interruptTimeSecond) {
        if (null == vo) {
            vo = new CapStatsVo();
            vo.setVo(ovo);
            vo.setK(cacheDlKey);
            vo.setCty(ovo.getSetType());
        }

        vo.setI(NumConstant.INT_ZERO);
        vo.setAc(NumConstant.DOUBLE_ZERO);
        vo.setC(interruptCap == null ? NumConstant.DOUBLE_ZERO : interruptCap.doubleValue());
        vo.setTs(interruptTimeSecond == null ? NumConstant.DOUBLE_ZERO : interruptTimeSecond.doubleValue());
        cachePutOrGet.putStatsCache(cacheDlKey, vo);

        var interruptStats = cachePutOrGet.getInterruptStatsCache(cacheDlKey);
        // 重新设置缓存数据
        if (null == interruptStats) {
            var ivo = new InterruptStatsCacheVo();
            ivo.setCap(vo.getC());
            ivo.setTs(vo.getTs());
            int t = ((int) vo.getTs()) / NumConstant.INT_TEN;
            int y = ((int) vo.getTs()) % NumConstant.INT_TEN;
            var interruptCount = y == NumConstant.INT_ZERO ? t : t + NumConstant.INT_ONE;
            ivo.setInterruptBeforeTimes(interruptCount);
            cachePutOrGet.putInterruptCapacityCache(cacheDlKey, ivo);
        }
    }

    private void operationSaveOrUpdate(CommandIssuedSuccess command, OperationDetail detail,
                                       boolean update, int boardNo, int channelNo, String batchNo, long endTime) {
        if (null == command || null == command.getStepId()) {
            return;
        }

        detail.setOrderNo(command.getOrder());
        detail.setCabinetNo(command.getReqCabinetNo());
        // 不是异常状态
        if (ServerConstant.START_FLAG_ERROR != detail.getStartFlag()) {
            detail.setStartFlag(ServerConstant.START_FLAG_NORMAL);
        } else {
            detail.setStartFlag(ServerConstant.START_FLAG_ERROR);
        }

        var nowTime = System.currentTimeMillis();
        // 终止操作,进行中状态才修改为终止状态
        if (null != command.getStepId() && NumConstant.LONG_LT_ZERO == command.getStepId()) {
            var key = command.getReqCabinetNo() + CaffeineUtil.CACHE_KEY_SYMBOL + boardNo + CaffeineUtil.CACHE_KEY_SYMBOL + channelNo;
            var s = cachePutOrGet.getStatsCache(key);
            if (null != s && ErrorTypeEnum.EXECUTING.getCode() == s.getT()) {
                detail.setStartFlag(ServerConstant.START_FLAG_DISABLE);
            }
        }

        detail.setUpdateTime(nowTime);
        detail.setBeginTime(nowTime);
        if (null != command.getStepId() && command.getStepId().intValue() > NumConstant.INT_ZERO) {
            detail.setStepId(command.getStepId().intValue());
        }

        // 设置整体工艺方案执行完成最后结束时间
        if (NumConstant.INT_ONE == command.getOrder() && null != command.getStepId() && command.getStepId() > NumConstant.LONG_ZERO) {
            detail.setStartFlag(ServerConstant.START_FLAG_NORMAL);
            detail.setOperationId(UUID.randomUUID().toString().replace("-", ""));
            detail.setFirstOrderTime(nowTime);
            // 获取批次号
            detail.setBatchNo(batchNo);
            detail.setEndTime(nowTime + (endTime * 60 * 1000L));
        }

        // 更新操作记录
        if (update) {
            detail.setInterruptCap(null);
            detail.setInterruptTimeSecond(null);
            //log.info("更新操作记录,detail:{}.ing:{}", detail, isIng);
            operationDetailMapper.updateDetail(detail);
            return;
        }

        // 新增操作记录
        operationDetailMapper.addDetail(detail);
    }

    private OperationDetail firstOperationProcess(CommandIssuedSuccess command, OperationDetail detail, int boardNo, int channelNo, String batchNo, long endTime) {
        if (null == command || null == command.getStepId()) {
            return detail;
        }

        detail.setOrderNo(command.getOrder());
        detail.setCabinetNo(command.getReqCabinetNo());
        // 不是异常状态
        if (ServerConstant.START_FLAG_ERROR != detail.getStartFlag()) {
            detail.setStartFlag(ServerConstant.START_FLAG_NORMAL);
        } else {
            detail.setStartFlag(ServerConstant.START_FLAG_ERROR);
        }

        var nowTime = System.currentTimeMillis();
        // 终止操作,进行中状态才修改为终止状态
        if (null != command.getStepId() && NumConstant.LONG_LT_ZERO == command.getStepId()) {
            var key = command.getReqCabinetNo() + CaffeineUtil.CACHE_KEY_SYMBOL + boardNo + CaffeineUtil.CACHE_KEY_SYMBOL + channelNo;
            var s = cachePutOrGet.getStatsCache(key);
            if (null != s && ErrorTypeEnum.EXECUTING.getCode() == s.getT()) {
                detail.setStartFlag(ServerConstant.START_FLAG_DISABLE);
            }
        }

        detail.setUpdateTime(nowTime);
        detail.setBeginTime(nowTime);
        if (null != command.getStepId() && command.getStepId().intValue() > NumConstant.INT_ZERO) {
            detail.setStepId(command.getStepId().intValue());
        }

        // 设置整体工艺方案执行完成最后结束时间
        if (NumConstant.INT_ONE == command.getOrder() && null != command.getStepId() && command.getStepId() > NumConstant.LONG_ZERO) {
            detail.setStartFlag(ServerConstant.START_FLAG_NORMAL);
            detail.setOperationId(UUID.randomUUID().toString().replace("-", ""));
            detail.setFirstOrderTime(nowTime);
            // 获取批次号
            detail.setBatchNo(batchNo);
            detail.setEndTime(nowTime + endTime * 60 * 1000L);
        }

        return detail;
    }


    private void interruptReIssuedOperationSaveOrUpdate(CommandIssuedSuccess command, OperationDetail detail) {
        if (null == command || null == command.getStepId()) {
            return;
        }

        detail.setOrderNo(command.getOrder());
        detail.setCabinetNo(command.getReqCabinetNo());
        detail.setStartFlag(ServerConstant.START_FLAG_NORMAL);

        var nowTime = System.currentTimeMillis();
        detail.setBeginTime(nowTime);
        detail.setUpdateTime(nowTime);
        if (null != command.getStepId() && command.getStepId().intValue() > NumConstant.INT_ZERO) {
            detail.setStepId(command.getStepId().intValue());
        }

        // 设置整体工艺方案执行完成最后结束时间
        if (NumConstant.INT_ONE == command.getOrder() && StringUtils.isBlank(detail.getOperationId())) {
            detail.setOperationId(UUID.randomUUID().toString().replace("-", ""));
        }

        //detail.setFirstOrderTime(nowTime);
        var timeCount = settingDetailMapper.queryTimeCountByStepId(command.getStepId(), command.getOrder());
        detail.setEndTime(nowTime + (timeCount * 60 * 1000L));

        // 更新操作记录
        detail.setInterruptCap(null);
        detail.setInterruptTimeSecond(null);
        //log.info("更新操作记录,detail:{}.ing:{}", detail, isIng);
        operationDetailMapper.updateDetail(detail);
    }

    private boolean isLast(Long stepId, Integer order) {
        var sd = settingDetailMapper.queryListByStepIdDesc(stepId);
        if (null == sd || null == sd.getIsDelete() || null == sd.getSettingOrder()) {
            log.info("判断是否是最后一个操作失败,查询无操作信息,stepId:{},order:{}", stepId, order);
            return false;
        }

        // 最后一个工步方案已经执行结束
        return order >= sd.getSettingOrder();
    }

    private Pair<List<OperationDetail>, List<OperationDetail>> getOperationPair(List<BoardConfig> boardConfigs,
                                                                                List<OperationDetail> ops,
                                                                                CommandIssuedSuccess command, String batchNo, long endTime) {
        if (CollectionUtils.isEmpty(boardConfigs)) {
            return Pair.of(null, null);
        }

        final int[] serial = {NumConstant.INT_ZERO};
        List<OperationDetail> odNewList = new ArrayList<>();
        List<OperationDetail> odUpdateList = new ArrayList<>();
        var thread0 = Thread.startVirtualThread(() -> {
            for (var b : boardConfigs) {
                // 最后一个工步操作是搁置类型
                serial[0]++;
                //var od = getOneOperation(command, b, serial[0], ops, batchNo, endTime);
                var od = getOneOperationNew(command, b, serial[0], ops, batchNo, endTime);
                if (null != od && null == od.getId()) {
                    odNewList.add(od);
                }
                if (null != od && null != od.getId()) {
                    odUpdateList.add(od);
                }
            }
        });

        try {
            thread0.join();
        } catch (Exception e) {
            log.error("operation error", e);
        }

        return Pair.of(odNewList, odUpdateList);
    }

    private void oneOperationUpdateFirst(List<OperationVo> ops, CommandIssuedSuccess command, BoardConfig b) {
        if (null == command || null == b) {
            return;
        }

        OperationVo vo = null;
        if (!CollectionUtils.isEmpty(ops)) {
            vo = ops.stream().filter(os -> os != null
                    && os.getCellNum().equals(b.getChannelNo())
                    && os.getBoardAddress().equals(b.getAddress())
                    && os.getCabinetNo().equals(command.getReqCabinetNo())).findFirst().orElse(null);
        }

        if (null == vo) {
            vo = operationDetailMapper.findLeftOn(command.getReqCabinetNo(), b.getChannelNo(), b.getAddress());
            if (null == vo) {
                //log.info("oneOperationUpdateFirst,vo is null,command:{},b:{}", command, b);
                var sd = settingDetailMapper.queryListByStepIdAndSettingOrder(Long.parseLong(String.valueOf(command.getStepId())), command.getOrder());
                vo = new OperationVo();
                vo.setCutOff(sd.getCutOff());
                vo.setCurrent(sd.getCurrent());
                vo.setSetType(sd.getSetType());
                vo.setStepId(command.getStepId());
                vo.setDetailsStepId(sd.getStepId());
                vo.setCutOffType(sd.getCutOffType());
                vo.setExpectedTime(sd.getExpectedTime());
                vo.setSettingOrder(sd.getSettingOrder());
                vo.setStartFlag(ServerConstant.START_FLAG_NORMAL);
                vo.setCabinetNo(String.valueOf(Integer.parseInt(command.getReqCabinetNo())));
                log.info("oneOperationUpdateFirst,vo is NOT null,command:{},VO:{}", gson.toJson(command), gson.toJson(vo));
            }
        }

        vo.setStartFlag(ServerConstant.START_FLAG_NORMAL);

        var opKey = KeyUtil.commandOperateKey(command.getReqCabinetNo(), b.getAddress(), b.getChannelNo());
        vo.setOperationStartTime(System.currentTimeMillis());
        operationVoCacheService.putOperationVo(opKey, vo);
        //log.info("[整体]循环单个通道工步指令操作缓存更新key={},vo={}", opKey, gson.toJson(operationVoCacheService.getOperationVo(opKey)));

        var cacheKey = command.getReqCabinetNo() + CaffeineUtil.CACHE_KEY_SYMBOL + b.getAddress() + CaffeineUtil.CACHE_KEY_SYMBOL + b.getChannelNo();
        // 每个电池通道的工步操作缓存,更新电池容量统计缓存
        var endFlag = vo.getDetailsStepId() == NumConstant.LONG_LT_TEN;
        var isDisable = vo.getStartFlag() == ServerConstant.START_FLAG_DISABLE;
        if (!endFlag) {
            cachePutOrGet.deleteCurrent(cacheKey);
            var stats = cachePutOrGet.getStatsCache(cacheKey);
            cacheInit(cacheKey, isDisable, stats, vo);
        }
    }


    private OperationDetail getOneOperation(CommandIssuedSuccess command, BoardConfig b, int batterySerial, List<OperationDetail> ops, String batchNo, long endTime) {
        if (null == command || null == b) {
            return null;
        }

        boolean addAll = CollectionUtils.isEmpty(ops);
        OperationDetail od = null;
        boolean isSingleAndIngNotUpdate = false;
        if (addAll) {
            od = new OperationDetail();
        } else {
            for (var o : ops) {
                if (o.getBoardAddress().equals(b.getAddress()) && o.getCellNum().equals(b.getChannelNo())) {
                    // 剔除正在执行的单个通道的
                    var isSingleAndIng = ServerConstant.SINGLE_TYPE_SINGLE == o.getSingleType()
                            && ServerConstant.START_FLAG_NORMAL == o.getStartFlag()
                            && null != o.getEndTime()
                            && o.getEndTime() > System.currentTimeMillis();
                    if (!isSingleAndIng) {
                        od = o;
                    } else {
                        isSingleAndIngNotUpdate = true;
                    }
                    break;
                }
            }
        }

        if (isSingleAndIngNotUpdate) {
            return null;
        }

        if (null == od) {
            od = new OperationDetail();
        }

        od.setCreateTime(System.currentTimeMillis());
        od.setStartFlag(ServerConstant.START_FLAG_NORMAL);

        od.setBatterySerial(batterySerial);
        od.setCellNum(b.getChannelNo());
        od.setBoardLineNum(b.getLineNo());
        od.setBoardAddress(b.getAddress());
        od.setSingleType(ServerConstant.SINGLE_TYPE_ALL);

        return firstOperationProcess(command, od, b.getAddress(), b.getChannelNo(), batchNo, endTime);
    }

    private OperationDetail getOneOperationNew(CommandIssuedSuccess command, BoardConfig b, int batterySerial, List<OperationDetail> ops, String batchNo, long endTime) {
        if (null == command || null == b) {
            return null;
        }

        var od = getOneOperationDetail(b, ops);
        if (od == null) {
            return null;
        }

        od.setCreateTime(System.currentTimeMillis());
        od.setStartFlag(ServerConstant.START_FLAG_NORMAL);

        od.setBatterySerial(batterySerial);
        od.setCellNum(b.getChannelNo());
        od.setBoardLineNum(b.getLineNo());
        od.setBoardAddress(b.getAddress());
        od.setSingleType(ServerConstant.SINGLE_TYPE_ALL);

        return firstOperationProcess(command, od, b.getAddress(), b.getChannelNo(), batchNo, endTime);
    }

    private OperationDetail getOneOperationDetail(BoardConfig b, List<OperationDetail> ops) {
        // 数据库表里没有一笔操作记录，全部通道的操作记录新增
        if (CollectionUtils.isEmpty(ops)) {
            return new OperationDetail();
        }

        // 数据库表里有操作记录的
        for (var o : ops) {
            // 比较通道,已经存在操作记录
            if (o.getBoardAddress().equals(b.getAddress()) && o.getCellNum().equals(b.getChannelNo())) {
                // 剔除正在执行的单个通道的
                var isSingleAndIng = ServerConstant.SINGLE_TYPE_SINGLE == o.getSingleType()
                        && ServerConstant.START_FLAG_NORMAL == o.getStartFlag()
                        && null != o.getEndTime() && o.getEndTime() > System.currentTimeMillis();
                // 存在操作记录而且是单通道且正在执行的,直接返回null 不新增也不更新操作记录
                if (isSingleAndIng) {
                    return null;
                }

                // 存在操作记录而且是单通道且已经执行完成的,直接操作记录 更新操作记录
                return o;
            }
        }

        return null;
    }


    private void oneOperationUpdate(CommandIssuedSuccess command, BoardConfig b, int batterySerial, String batchNo, long endTime) {
        if (null == command || null == b) {
            return;
        }

        // 最后一个工步操作是搁置类型
        var od = operationDetailMapper.findOneDetail(command.getReqCabinetNo(), b.getAddress(), b.getChannelNo(), b.getLineNo());
        // 剔除正在执行的单个通道的
        var isSingleAndIng = null != od
                && ServerConstant.SINGLE_TYPE_SINGLE == od.getSingleType()
                && ServerConstant.START_FLAG_NORMAL == od.getStartFlag()
                && null != od.getEndTime()
                && od.getEndTime() > System.currentTimeMillis();

        var error = null != od && ServerConstant.START_FLAG_ERROR == od.getStartFlag()
                && NumConstant.INT_ONE != command.getOrder();
        if (isSingleAndIng || error) {
            log.info("[整体]循环单个通道执行中或者异常的而且结束时间未到:{}", gson.toJson(od));
            return;
        }

        var update = true;
        if (null == od) {
            update = false;
            od = new OperationDetail();
            od.setCreateTime(System.currentTimeMillis());
            od.setStartFlag(ServerConstant.START_FLAG_NORMAL);
        }
        //serial[0]++;
        od.setBatterySerial(batterySerial);
        od.setCellNum(b.getChannelNo());
        od.setBoardLineNum(b.getLineNo());
        od.setBoardAddress(b.getAddress());
        od.setSingleType(ServerConstant.SINGLE_TYPE_ALL);

        operationSaveOrUpdate(command, od, update, b.getAddress(), b.getChannelNo(), batchNo, endTime);

        // 增加缓存
        var vo = operationDetailMapper.findLeftOn(command.getReqCabinetNo(), b.getChannelNo(), b.getAddress());
        if (null == vo) {
            log.info("[整体]循环单个通道执行未找到操作信息:{}-{}-{}", command.getReqCabinetNo(), b.getAddress(), b.getChannelNo());
            return;
        }

        vo.setStartFlag(ServerConstant.START_FLAG_NORMAL);

        var opKey = KeyUtil.commandOperateKey(command.getReqCabinetNo(), b.getAddress(), b.getChannelNo());
        vo.setOperationStartTime(System.currentTimeMillis());
        operationVoCacheService.putOperationVo(opKey, vo);
        //log.info("[整体]循环单个通道工步指令操作缓存更新key={},vo={}", opKey, gson.toJson(operationVoCacheService.getOperationVo(opKey)));

        var cacheKey = command.getReqCabinetNo() + CaffeineUtil.CACHE_KEY_SYMBOL + b.getAddress() + CaffeineUtil.CACHE_KEY_SYMBOL + b.getChannelNo();
        // 每个电池通道的工步操作缓存,更新电池容量统计缓存
        var endFlag = vo.getDetailsStepId() == NumConstant.LONG_LT_TEN;
        var isDisable = vo.getStartFlag() == ServerConstant.START_FLAG_DISABLE;
        if (!endFlag) {
            cachePutOrGet.deleteCurrent(cacheKey);
            var stats = cachePutOrGet.getStatsCache(cacheKey);
            cacheInit(cacheKey, isDisable, stats, vo);
        }
    }

    private void operationVoCacheUpdateAllChannel(List<BoardConfig> boardConfigs, CommandIssuedSuccess command, String batchNo, long endTime) {
        if (CollectionUtils.isEmpty(boardConfigs) || null == command) {
            return;
        }

        final int[] serial = {NumConstant.INT_ZERO};
        var thread = Thread.startVirtualThread(() -> {
            for (var b : boardConfigs) {
                var opKey = KeyUtil.commandOperateKey(command.getReqCabinetNo(), b.getAddress(), b.getChannelNo());
                var cacheDlKey = Integer.parseInt(command.getReqCabinetNo()) + CaffeineUtil.CACHE_KEY_SYMBOL + b.getAddress() + CaffeineUtil.CACHE_KEY_SYMBOL + b.getChannelNo();
                cachePutOrGet.delInterruptStatsCache(cacheDlKey);
                // 最后的结束指令,更新操作记录信息状态
                var updateVo = operationVoCacheService.getOperationVo(opKey);
                if (null != updateVo) {
                    updateVo.setStartFlag(ServerConstant.START_FLAG_FINISH);
                    updateVo.setOperationStartTime(System.currentTimeMillis());
                    operationVoCacheService.putOperationVo(opKey, updateVo);
                }

                // 不是搁置类型
                if (null != command.getSetType() && !StepTypeNoEnum.STEP_TYPE_SL_NUM.getCode().equalsIgnoreCase(command.getSetType())) {
                    log.info("[整体]下发指令操作,最后的结束指令判断是否是搁置类型：{}", gson.toJson(command));
                    continue;
                }

                // 最后一个工步操作是搁置类型
                serial[0]++;
                oneOperationUpdate(command, b, serial[0], batchNo, endTime);
            }
        });

        try {
            thread.join();
        } catch (Exception e) {
            log.error("operation error", e);
        }
    }
}
